
#include "commmsg.h"
#include "../online/onlineuser.h"
#include "../mainctrl.h"
#include "../cmd/dataprepare.h"
#include "cmdgift.h"

#define MAX_ONLEINE_GIFT_COUNT  6   //在线礼包数的最多发放
CT_REGISTER_ASYNCCMD(ID_MAIN_ONLINE_GIFT, CCmdOnlineGift);
int CCmdOnlineGift::Do(void* pData)
{
    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_ONLINE_GIFT ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Tpye=%d",
            ID_MAIN_ONLINE_GIFT,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    int iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }
    //消息解析结束

    //检查登录
    _uiGID = stReq.gid();
    iRet = pstMainCtrl->CheckLogin(_uiGID, stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    LogicDo(RET_OK);
    return RET_OK;
}

int CCmdOnlineGift::LogicDo(int iRet)
{
    if (iRet)
    {
        return AnsClients(iRet);
    }

    PREPARE_PLAYER_BASE_INFO(this, stReq.gid());
    PREPARE_PLAYER_DETAIL_INFO(this, stReq.gid());
    PREPARE_PLAYER_ONLINE_DATA(this, stReq.gid());

    int iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerBaseInfo & stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

    if (stPlayerBaseInfo._ucIsInited != 1)
    {
        return AnsClients(ERROR_NOT_INITED);
    }

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerDetailInfo& stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];
    CGiftData & stGiftData = stPlayerDetailInfo._stGiftData;

    iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        CT_ERROR(("user %u not in m_stPlayerOnlineDataHash", _uiGID));
        return AnsClients(RET_SYSTEM_FAIL);

    }
    CPlayerOnlineData & stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    int iHaveGetedGiftCnt = stPlayerDetailInfo._stGiftData._iOnlineGiftCnt;
    bool bNeedSaveDetail = false;

    unsigned char ucOpt = stReq.opt();
    CDropItem  stGiftItem;

    int iThisOnlineTime = 0;
    iRet = pstMainCtrl->m_stPlayerOnline.GetUserOnlineTime(_uiGID, pstMainCtrl->m_iNow, iThisOnlineTime);
    if (iRet)
    {
        CT_ERROR(("%d", _uiGID));
        return AnsClients(ERROR_GIFT_ONLINE_TIME);
    }

    int iTotalOnlineTime = stPlayerBaseInfo._iOnlineTimeSinceReg + iThisOnlineTime;
    if (iTotalOnlineTime < stGiftData._iGiftTime) 
    {
        //修正异常的时间, 保证领取下个在先礼包时的异常
        CT_WARNING(("%d, %d, %d", _uiGID, iTotalOnlineTime, stGiftData._iGiftTime));

        stGiftData._iGiftTime = iTotalOnlineTime;
        
        CVarObjectKey stKey;
        stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
        stKey.m_u64ID = stPlayerDetailInfo._uiGID;
        pstMainCtrl->UpdateData(stKey, stPlayerDetailInfo, VOP_UPDATE);
    }

    int iAvailTime = GetGiftAvailTime(stPlayerDetailInfo._stGiftData._iGiftTime, iTotalOnlineTime, iHaveGetedGiftCnt);
    if (1 == ucOpt)         //1:获取在线礼包信息,
    {
        if (iHaveGetedGiftCnt >= MAX_ONLEINE_GIFT_COUNT)
        {
            stAns.set_available_time(0);
            stAns.set_gift_id(0);
        }
        else
        {
            unsigned int uiGiftID = iHaveGetedGiftCnt + 1;  //待领取的在线礼包ID分别是 1,2,3,4,5,6
            stAns.set_available_time(iAvailTime);
            stAns.set_gift_id(uiGiftID);
            iRet = pstMainCtrl->m_stItemMgr.GetGiftItem(uiGiftID, _uiGID, stGiftItem);
        }
    }
    else if (2 == ucOpt)    //2: 领取在线礼包.
    {
        if (iHaveGetedGiftCnt >= MAX_ONLEINE_GIFT_COUNT ||
            pstMainCtrl->m_iNow < iAvailTime)  //超过数目 or  未到可领时间
        {
            CT_WARNING(("%d, %d, %d", iHaveGetedGiftCnt, iAvailTime, pstMainCtrl->m_iNow));
            return AnsClients(ERROR_ONLEINE_GIFT_OPEN);
        }

        if (stPlayerOnlineData._stUserStorage.BagIsFull())
        {
            return AnsClients(ERROR_STORAGE_BAG_IS_FULL);
        }

        unsigned int uiGiftID = iHaveGetedGiftCnt + 1;  //待领取的在线礼包ID分别是 1,2,3,4,5,6
        iRet = pstMainCtrl->m_stStorageMgr.OpenGift(stPlayerOnlineData._stUserStorage, uiGiftID, _uiGID, stGiftItem);
        if (RET_OK == iRet)
        {
            iHaveGetedGiftCnt += 1;
            stGiftData._iOnlineGiftCnt = iHaveGetedGiftCnt;
            stGiftData._iGiftTime = iTotalOnlineTime;
            bNeedSaveDetail = true;

            unsigned int uiNextGiftId = uiGiftID + 1;
            if (stPlayerDetailInfo._stGiftData._iOnlineGiftCnt < MAX_ONLEINE_GIFT_COUNT)
            {
                iRet = pstMainCtrl->m_stItemMgr.GetGiftItem(uiNextGiftId, _uiGID, stGiftItem, true);
                if (iRet)
                {
                    CT_ERROR(("%d, %d", uiNextGiftId, iRet));
                }

                iAvailTime = GetGiftAvailTime(stGiftData._iGiftTime, iTotalOnlineTime, iHaveGetedGiftCnt);
                stAns.set_available_time(iAvailTime);
                stAns.set_gift_id(uiNextGiftId);
            }
            else
            {
                stAns.set_available_time(0);
                stAns.set_gift_id(0);
                stGiftItem.Clear();
            }
        }
        else
        {
            stAns.set_op_ret(iRet);
            iRet = RET_OK;
        }
    }
    else
    {
        return AnsClients(ERROR_ONLINE_GIFT_OPT);
    }

    stGiftItem.GetPBMsg(_uiGID, *(stAns.mutable_gift_items()));

    if (bNeedSaveDetail)
    {
        pstMainCtrl->m_stStorageMgr.GetData(stPlayerOnlineData._stUserStorage, stPlayerDetailInfo._stUserStorage);

        CVarObjectKey stKey;
        stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
        stKey.m_u64ID = stPlayerDetailInfo._uiGID;
        pstMainCtrl->UpdateData(stKey, stPlayerDetailInfo, VOP_UPDATE);
    }

    return AnsClients(iRet);
}

int CCmdOnlineGift::AnsClients(int iRet)
{
    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    stAns.set_opt(stReq.opt());
    pstMainCtrl->m_stEncodeBuf.Clear();
    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);
    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf, true))
    {
        CT_WARNING((""));
        return Done(RET_SYS_ERROR);
    }

    return Done(iRet);
}

int CCmdOnlineGift::GetGiftAvailTime (int iGiftTime, int iTotalOnlinTime, int iHaveGotGiftCnt)
{
    if (iHaveGotGiftCnt >= MAX_ONLEINE_GIFT_COUNT)
    {
        return 0;
    }
    
    int astOnlineTime[MAX_ONLEINE_GIFT_COUNT] = {180, 360, 600, 900, 1200, 1800};   //领取奖励的时间点    

    int iOffSetTime = (astOnlineTime[iHaveGotGiftCnt] + iGiftTime) - iTotalOnlinTime;

    int iAvailTime = 0;   

    //礼包可领取的绝对时间戳 (小于当前时间表示可以领取,且未领取过)
    iAvailTime = pstMainCtrl->m_iNow + iOffSetTime;
    
    CT_TRACE(("iGiftTime: %d, iTotalOnlinTime: %d, iHaveGotGiftCnt: %d, iAvailTime: %d", iGiftTime, iTotalOnlinTime, iHaveGotGiftCnt, iAvailTime - pstMainCtrl->m_iNow));

    return iAvailTime;
}

CT_REGISTER_ASYNCCMD(ID_MAIN_GIFT_OPT, CCmdGiftOpt);
int CCmdGiftOpt::Do(void* pData)
{
    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_GIFT_OPT ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Tpye=%d",
            ID_MAIN_GIFT_OPT,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    int iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }
    //消息解析结束

    //检查登录
    _uiGID = stReq.gid();
    bNeedSaveBase = false;
    bNeedSaveDetail = false;

    iRet = pstMainCtrl->CheckLogin(_uiGID, stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    LogicDo(RET_OK);
    return RET_OK;
}

int CCmdGiftOpt::LogicDo(int iRet)
{
    if (iRet)
    {
        return AnsClients(iRet);
    }

    PREPARE_PLAYER_BASE_INFO(this, stReq.gid());
    PREPARE_PLAYER_DETAIL_INFO(this, stReq.gid());
    PREPARE_PLAYER_ONLINE_DATA(this, stReq.gid());

    int iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerBaseInfo & stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

    if (stPlayerBaseInfo._ucIsInited != 1)
    {
        return AnsClients(ERROR_NOT_INITED);
    }

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerDetailInfo& stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(_uiGID);
    if (iIndex < 0)
    {
        CT_ERROR(("user %u not in m_stPlayerOnlineDataHash", _uiGID));
        return AnsClients(RET_SYSTEM_FAIL);
    }
    CPlayerOnlineData & stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    CUserStorage& stUserStorage = stPlayerOnlineData._stUserStorage;
    unsigned int uiNotify = 0;
    CDropItem stGiftItem;
    switch (stReq.opt())
    {
    case 1: //获取用户待领取的礼包.
        {
            T_PENDING_ACT stPendingAct;
            pstMainCtrl->m_stGiftMgr.GetPendingAct(stPlayerBaseInfo, stPlayerDetailInfo, stPendingAct);
            for (int i = 0; i < stPendingAct.Size(); i++)
            {
                stAns.add_available_gifts(stPendingAct[i]);
            }

            for (int i = 0; i < stPlayerDetailInfo._stGiftData._astPendingBonus.Size(); i++)
            {
                stAns.add_available_gifts(stPlayerDetailInfo._stGiftData._astPendingBonus[i]._uiItemID);
            }
        }
        break;

    case 2: //领取活动的奖励
        {
            iRet = FetchBonus(stPlayerBaseInfo, stPlayerDetailInfo, stPlayerOnlineData, stGiftItem);
            if (iRet == RET_OK)
            {
                bNeedSaveBase = true;
                bNeedSaveDetail = true;
            }
        }
        break;

    case 3:   //预览礼包中物品.
        {
            iRet = pstMainCtrl->m_stStorageMgr.PreViewGiftInfo(stUserStorage, stReq.gift_id(), _uiGID, stGiftItem);
            if (RET_OK != iRet)
            {
                stAns.set_opt_ret(iRet);
                iRet = RET_OK;
            }
        }
        break;

    case 4:   //打开礼包.
        {
            iRet = pstMainCtrl->m_stStorageMgr.OpenGiftInBag(stUserStorage, (unsigned short)stReq.pos(), _uiGID, stGiftItem);
            if (RET_OK == iRet)
            {
                bNeedSaveDetail = true;
                uiNotify = NOTIFY_BAG_INFO;
            }
            else
            {
                stAns.set_opt_ret(iRet);
                iRet = RET_OK;
            }
        }
        break;

    case 5:   //一键开礼包
        {
            int iOptRet = RET_OK;
            iRet = pstMainCtrl->m_stStorageMgr.OneKeyOpenGiftInBag(stUserStorage, (unsigned short)stReq.pos(), _uiGID, stGiftItem, iOptRet);
            if (RET_OK == iRet)
            {
                bNeedSaveDetail = true;                
                stAns.set_opt_ret(iOptRet);

                if (stGiftItem.Size() > 0)
                {
                    uiNotify = NOTIFY_BAG_INFO;
                }
            }
        }
        break;

    default:
        {
            iRet = ERROR_UNSURPORT_BAG_OPT;
        }
    }

    if (iRet)
    {
        return AnsClients(iRet);
    }

    stGiftItem.GetPBMsg(_uiGID, *(stAns.mutable_gift_items()));
    if (bNeedSaveBase)
    {
        CVarObjectKey stKey;
        stKey.m_chDataType = DT_PLAYER_BASE_INFO;
        stKey.m_u64ID = stPlayerBaseInfo._uiGID;
        pstMainCtrl->UpdateData(stKey, stPlayerBaseInfo, VOP_UPDATE);
    }

    if (bNeedSaveDetail)
    {
        pstMainCtrl->m_stStorageMgr.GetData(stUserStorage, stPlayerDetailInfo._stUserStorage);

        CVarObjectKey stKey;
        stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
        stKey.m_u64ID = stPlayerDetailInfo._uiGID;
        pstMainCtrl->UpdateData(stKey, stPlayerDetailInfo, VOP_UPDATE);
    }

    pstMainCtrl->m_stNotifyMgr.Notify(_uiGID, uiNotify);
    return AnsClients(RET_OK);
}

int CCmdGiftOpt::AnsClients(int iRet)
{
    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);
    stAns.set_opt(stReq.opt());
    stAns.set_gift_id(stReq.gift_id());
    pstMainCtrl->m_stEncodeBuf.Clear();
    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);
    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf, true))
    {
        CT_WARNING((""));
        return Done(RET_SYS_ERROR);
    }

    return Done(iRet);
}

int CCmdGiftOpt::FetchBonus (CPlayerBaseInfo & stPlayerBaseInfo, CPlayerDetailInfo & stPlayerDetailInfo, CPlayerOnlineData & stPlayerOnlineData, CDropItem & stGainItems)
{
    int iRet = 0;
    CUserStorage& stUserStorage = stPlayerOnlineData._stUserStorage;

    StorageItemData  stItem;
    stItem._ucItemType = ITEM_TYPE_GIFT;
    stItem._uiItemID = stReq.gift_id();

    if (stPlayerDetailInfo._stGiftData.HasBonus(stItem))
    {
        CGiftConfigUnit stCfg;
        iRet = pstMainCtrl->m_stItemMgr.GetGiftConfig (stItem._uiItemID, stCfg);
        if (iRet)
        {
            CT_ERROR(("%d", stItem._uiItemID));
            return iRet;
        }

        if (stCfg._bDirectOpen)
        {
            iRet = pstMainCtrl->m_stStorageMgr.OpenGift(stUserStorage, stItem._uiItemID, _uiGID, stGainItems);
            if (iRet)
            {
                CT_ERROR(("%d, %d.", stItem._uiItemID, iRet));
            }
        }
        else
        {
            iRet = pstMainCtrl->m_stStorageMgr.AddItem(stUserStorage, ITEM_TYPE_GIFT, stItem._uiItemID, 1);
            if (iRet == RET_OK)
            {
                stGainItems.DropItem(stItem._uiItemID, ITEM_TYPE_GIFT, 1);
                pstMainCtrl->m_stNotifyMgr.Notify(_uiGID, NOTIFY_BAG_INFO);
            }
        }

        if (iRet == RET_OK)
        {
            stPlayerDetailInfo._stGiftData.DelBonus(stItem);
        }
    }
    else
    {
        iRet = pstMainCtrl->m_stGiftMgr.FetchPendingItem(stPlayerBaseInfo, stPlayerDetailInfo, stItem._uiItemID, stGainItems);
    }

    return iRet;
}


